package edu.hcmus.sow.web.user;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import edu.hcmus.sow.dao.AuthoritiesDAO;
import edu.hcmus.sow.dao.GroupDAO;
import edu.hcmus.sow.dao.UserDAO;
import edu.hcmus.sow.dao.UserProfileDAO;
import edu.hcmus.sow.domain.Group;
import edu.hcmus.sow.domain.User;
import edu.hcmus.sow.domain.UserProfile;
import edu.hcmus.sow.service.UserService;
import edu.hcmus.sow.utils.SecurityUtil;

@Controller
public class UserController {
   @Autowired
   private UserDAO userDAO;

   @Autowired
   private UserProfileDAO userProfileDAO;

   @Autowired
   private AuthoritiesDAO authoritiesDAO;

   @Autowired
   private GroupDAO groupDAO;

   @Autowired
   private UserService userService;

   @RequestMapping("/admin/users")
   public ModelAndView display() throws Exception {
      List<Group> groups = groupDAO.getGroups(SecurityUtil.getCurrentClient());
      String groupsJson = new ObjectMapper().writeValueAsString(groups);

      ModelAndView mav = new ModelAndView();
      mav.addObject("groups", groupsJson);
      mav.setViewName("admin/users");
      return mav;
   }

   @RequestMapping("/admin/user/search")
   @ResponseBody
   public List<Map<String, String>> search(@RequestParam(value = "firstName", required = false) String firstName,
         @RequestParam(value = "lastName", required = false) String lastName,
         @RequestParam(value = "username", required = false) String username,
         @RequestParam(value = "group", required = false) String group) {

      List<Map<String, String>> result = new ArrayList<Map<String, String>>();
      Integer groupId = StringUtils.isEmpty(group) || "All".equals(group) ? null : new Integer(group);
      List<UserProfile> profiles = userProfileDAO.findByCriteria(SecurityUtil.getCurrentClient(),
            StringUtils.trimToEmpty(firstName), StringUtils.trimToEmpty(lastName), StringUtils.trimToEmpty(username),
            groupId);

      for (UserProfile profile : profiles) {
         Map<String, String> map = new HashMap<String, String>();
         map.put("id", profile.getUserByUserId().getId().toString());
         map.put(
               "name",
               profile.getFirstName()
                     + (StringUtils.isEmpty(profile.getMiddleName()) ? "" : " " + profile.getMiddleName()) + " "
                     + profile.getLastName());
         map.put("username", profile.getUserByUserId().getUsername());
         map.put("email", profile.getEmail());
         map.put("phone", profile.getPhone());
         map.put("enabled", profile.getUserByUserId().getEnabled().toString());
         map.put("role", userService.getRole(profile.getUserByUserId().getId()).getAuthority());
         result.add(map);
      }

      return result;
   }

   @RequestMapping("/ajax/admin/user")
   public ModelAndView displayUser(@RequestParam(value = "id", required = false) Integer id) {
      UserForm userForm = new UserForm();
      if (id != null) {
         UserProfile profile = userProfileDAO.getByUserID(id);
         userForm.setId(id);
         userForm.setUsername(profile.getUserByUserId().getUsername());
         userForm.setEnabled(profile.getUserByUserId().getEnabled());
         userForm.setFirstName(profile.getFirstName());
         userForm.setLastName(profile.getLastName());
         userForm.setMiddleName(profile.getMiddleName());
         userForm.setEmail(profile.getEmail());
         userForm.setPhone(profile.getPhone());
         userForm.setRole(userService.getRole(id).getId());
      } else {
         userForm.setRole(userService.getDefaultRole().getId());
      }

      ModelAndView mav = new ModelAndView();
      mav.addObject("userForm", userForm);
      mav.addObject("roles", authoritiesDAO.findAll());
      mav.setViewName("controls/user_form");
      return mav;
   }

   /**
    * Save an existing User entity
    * 
    */
   @RequestMapping(value = "/ajax/admin/user/save", method = RequestMethod.POST)
   public ModelAndView saveUser(@Valid UserForm userForm, BindingResult result) {
      userForm.validate(result, userDAO);

      if (!result.hasErrors()) {
         User user = userService.saveUser(userForm.getId(), userForm.getUsername(), userForm.getPassword(),
               userForm.getEnabled());
         userService.saveUserProfile(user, userForm.getFirstName(), userForm.getLastName(), userForm.getMiddleName(),
               userForm.getEmail(), userForm.getPhone());
         userService.updateUserRole(user, userForm.getRole());
         userForm.setId(user.getId());
      }

      ModelAndView mav = new ModelAndView();
      mav.addObject("userForm", userForm);
      mav.addObject("roles", authoritiesDAO.findAll());
      mav.addObject("hasErrors", result.hasErrors());
      mav.setViewName("controls/user_form");
      return mav;
   }

   @RequestMapping(value = "/ajax/admin/user/delete", method = RequestMethod.POST)
   @ResponseBody
   public String deleteUser(@RequestParam(value = "id", required = true) Integer id) {
      if (userService.deleteUser(id))
         return "success";
      return "error";
   }

   @RequestMapping(value = "/ajax/user/search", produces = "application/json")
   @ResponseBody
   public List<Map<String, String>> getUsers(@RequestParam("approver") String name) {

      Integer clientID = SecurityUtil.getCurrentClient();
      List<UserProfile> list = userProfileDAO.findByName(clientID, name);

      List<Map<String, String>> items = new ArrayList<Map<String, String>>();
      for (UserProfile u : list) {
         Map<String, String> item = new HashMap<String, String>();
         item.put("id", u.getUserByUserId().getId().toString());
         item.put("name", u.getFirstName() + " " + u.getLastName());
         item.put("username", " (" + u.getUserByUserId().getUsername() + ")");
         items.add(item);
      }
      return items;
   }

   @RequestMapping(value = "/ajax/project/{projectID}/users")
   @ResponseBody
   public List<User> getUsersByProject(@PathVariable("projectID") String projectID) {
      List<User> list = userDAO.findAll();

      return list;
   }
}
